#ifndef UNIAST_RUNTIME_VISITOR_H
#define UNIAST_RUNTIME_VISITOR_H

#include "AST/UniASTNode.h"
#include "symbolTable/SymbolTable.h"

#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/TypeRange.h"
#include "mlir/IR/ValueRange.h"
#include "mlir/IR/Verifier.h"
#include "mlir/InitAllPasses.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopedHashTable.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"

#include <functional>
#include <string>

namespace UniAST
{
class BasicVisitor
{
  private:
    std::map<std::string, std::function<std::any(TreeNode *)>>
        visitFunctions;
    Manager &manager;
    mlir::MLIRContext mlirContext;
    mlir::OpBuilder builder;
    mlir::ModuleOp theModule;
    void
    registerFunction(std::string nodeName,
                     std::function<std::any(TreeNode *)> visitFunction);
    mlir::Location getLocation(UniAST::TreeNode *node);

  public:
    BasicVisitor();
    virtual ~BasicVisitor();
    virtual std::any visitChildren(TreeNode *node);
    virtual std::any visit(TreeNode *node);
    virtual std::any visitRoot(TreeNode *node);
    virtual std::any visitModule(TreeNode *node);
    virtual std::any visitAssign_stmt(TreeNode *node);
    virtual std::any visitVariable_access(TreeNode *node);
    virtual std::any visitName_access(TreeNode *node);
    virtual std::any visitExpression(TreeNode *node);
    virtual std::any visitOp(TreeNode *node);
    virtual std::any visitExpr_params(TreeNode *node);
    virtual std::any visitExpr_param(TreeNode *node);
    virtual std::any visitNUMBER(TreeNode *node);
    virtual std::any visitTEXT(TreeNode *node);
    virtual std::any visitLiteral(TreeNode *node);
    virtual std::any visitADDOP(TreeNode *node);
    virtual std::any visitSUBOP(TreeNode *node);
};

} // namespace UniAST

#endif